using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web.Mvc;
using System.Xml.Linq;
using EPiServer.Common.Categories;
using EPiServer.Community.Blog;
using JoelAbrahamsson.BlogExtensions;

namespace JoelAbrahamsson.Web.Controllers
{
    public class RssController : Controller
    {
        ExtendedBlogHandlerFacade _blogHandlerFacade;
        BlogCategoryProvider _categoryProvider;

        public RssController(ExtendedBlogHandlerFacade blogHandlerFacade, BlogCategoryProvider categoryProvider)
        {
            _blogHandlerFacade = blogHandlerFacade;
            _categoryProvider = categoryProvider;
        }

        public ContentResult Index(Blog blog)
        {
            int totalItems;
            EntryCollection latestEntries = _blogHandlerFacade.GetLatestEntries(blog, 1, 10, out totalItems);

            XDocument rss = CreateRssFeed(latestEntries, "Joel Abrahamsson", "http://joelabrahamsson.com" + Url.RouteUrl(new { controller = "RSS", action = "Index" }));

            return Content(rss.ToString(), "application/rss+xml");
        }

        private XDocument CreateRssFeed(IEnumerable<Entry> entries, string feedName, string feedLink)
        {
            string encoding = Response.ContentEncoding.WebName;
            return new XDocument(new XDeclaration("1.0", encoding, "yes"), 
                 new XElement("rss", new XAttribute("version", "2.0"),
                      new XElement("channel", 
                      new XElement("title", feedName),
                      new XElement("description", feedName),
                      new XElement("link", feedLink),
                      from entry in entries
                      select new XElement("item",
                          new XElement("title", entry.Title),
                          new XElement("description", entry.Content),
                          new XElement("link", entry.GetUrl(ControllerContext.RequestContext)),
                          new XElement("guid", entry.GetUrl(ControllerContext.RequestContext)),
                          new XElement("pubDate", entry.GetPublicationDate().ToString("ddd, dd MMM yyyy HH:mm:ss +0100", CultureInfo.InvariantCulture))
                          )
                      )
                 )
            );
        }

        public ContentResult EpiserverWorld(Blog blog)
        {
            IEnumerable<Entry> entries = GetEpiserverEntries();

            XDocument rss = CreateRssFeed(entries.Distinct(new EntryEqualityComparer()), "Joel Abrahamsson - Posts about EPiServer products", Url.RouteUrl(new { controller = "RSS", action = "EpiserverWorld" }));

            return Content(rss.ToString(), "application/rss+xml");
        }

        private IEnumerable<Entry> GetEpiserverEntries()
        {
            List<ICategory> episerverCategories = GetEpiserverCategories();

            return GetEntriesInCategories(episerverCategories).Take(10);
        }

        private List<ICategory> GetEpiserverCategories()
        {
            List<ICategory> episerverCategories = new List<ICategory>();
            foreach (ICategory childCategory in _categoryProvider.BlogCategoriesRoot.Children)
            {
                episerverCategories.AddRange(childCategory.Children.Where(category => category.Name.ToLower().Contains("episerver")));
            }
            return episerverCategories;
        }

        private IEnumerable<Entry> GetEntriesInCategories(List<ICategory> categories)
        {
            List<Entry> entries = new List<Entry>();
            int totalItems;
            foreach (ICategory category in categories)
            {
                entries.AddRange(category.GetCategorizedItems(typeof(Entry), 1, int.MaxValue - 1, out totalItems)
                    .Cast<Entry>()
                    .Where(entry => entry.PublicationStart <= DateTime.Now)
                );
            }
            return entries
                .Where(entry => entry.PublicationStart < DateTime.Now)
                .Distinct(new EntryEqualityComparer())
                .OrderByDescending(entry => entry.GetPublicationDate());
        }

        private class EntryEqualityComparer : IEqualityComparer<Entry>
        {

            public bool Equals(Entry x, Entry y)
            {
                return x.ID == y.ID;
            }

            public int GetHashCode(Entry obj)
            {
                return obj.ID;
            }
        }

    }
}
